iT邦幫忙

2023 iThome 鐵人賽

DAY 19
1
Software Development

再騙小心沒朋友🥵 用LIFF實作LINE整人工具系列 第 19

[Day19] 不懂JavaScript 只好等著被整😔 Promise篇

  • 分享至 

  • xImage
  •  

Promise 是在 JavaScript ES6 版本開始出現的新特性,Promise 可以提供非同步流程一個錯誤處理機制。如果有好幾件非同步的工作,每一件都要依賴前一件工作的結果,又必須按照順序完成,就會變成很可怕的Callback Hell(像下面這張圖):

使用Promise結構可以簡化成這樣,可讀性高很多:

a()
  .then(b)
  .then(c)
  .then(d)
  .then(e)
  .then(f)
  .catch() // Error Handling

在講解Promise之前要先說明同步、非同步工作的差別。

同步/非同步工作

單從字面上的意思來看,很容易以為同步是同時起步,非同步是不同時起步。其實完全不是這樣,「步」可以想像成「步道」,也就是說同步是每個工作都在同一個步道,每個工作都要等前一個工作做完才能執行:非同步是每個工作都各自在不同步道執行。

如果每個工作都很快結束那倒還好,但是 JavaScript 常被用來處理遠端網頁請求這種需要時間等待的作業,於是非同步作業的處理就變得相當重要。

Promise的概念

聽到Promise下意識應該都會想到英文的「承諾」,這邊舉一個例子簡單說明Promise的概念:

我和公司承諾我每天都會去上班,絕對不會缺席。但是今天早上我不小心睡過頭,眼看已經快遲到了,現在有兩個選項:

  1. 搭計程車
  2. 搭公車(叫不到計程車的話)
    如果搭計程車的話我就能準時到公司,成功解決我睡過頭的困境。但如果叫不到計程車我就只能搭公車,淪落到搭公車我必定遲到,會被主管罵到臭頭,但是無論如何我都會去上班打卡,只是打卡時間(會不會被罵)的差別而已。

把這個情境用 Promise 的方法來看,我跟公司的承諾就是 new Promise ,搭到計程車就是 resolve,搭公車就是 reject。
而搭到計程車表示成功,then 後就是準時打卡開始工作;搭到公車代表失敗,catch 後就是遲到被主管抓到罵到臭頭。不管是搭計程車還是搭公車我都還是要工作,只是過程的差別而已。

Promise 的語法

new Promise(function(resolve, reject) { 
	resolve(); // 正確完成的回傳方法
	reject();  // 失敗的回傳方法
});
  • resolve 和 reject 的名稱可以自己定義,分別代表成功與失敗的回傳結果。
  • resolve 和 reject 一定只能回傳其中之一,而且只能回傳一次。
    在 Promise 的執行過程中,可以看到以下三種狀態:
  1. 擱置(pending):初始狀態,表示事件已經運行中,尚未取得結果。(像在叫車的過程)
  2. 實現(fulfilled):表示事情已經成功完成。(搭到計乘車沒有遲到)
  3. 拒絕(rejected):表示事情執行完畢但操作失敗。(搭公車遲到被主管罵爆)

Promise 實際範例

let GetInTaxi = false;

let p = new Promise(function(resolve,reject){
	if (GetInTaxi){
		console.log("Go to work on time.");
		resolve();
	}else{
		console.log("Can't get in taxi.");
		reject();
	}
});
p.then(function() {console.log("promise resolved.")})
.catch(function() {console.log("promise rejected.")});


先宣告一個參數(GetInTaxi),然後把參數的值設定為 false 觀察 promise reject 的結果。實務上 false 的值不能人工去指定,要等前一個工作完成的回傳結果或是在執行遠端資料回傳的結果自動代入值。當 GetInTaxi 參數值為 True 的執行結果:


上一篇
[Day18] 不懂JavaScript 只好等著被整😔 箭頭函式篇
下一篇
[Day20] 不懂JavaScript 只好等著被整😔 Async Await篇
系列文
再騙小心沒朋友🥵 用LIFF實作LINE整人工具30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言